package com.moonfish.base.controller;

import com.moonfish.base.controller.Response.BaseResponseBody;
import com.moonfish.base.controller.Response.ErrCode;
import com.moonfish.base.controller.Response.MenuResponseBody;
import com.moonfish.base.controller.request.MenuRequestBody;
import com.moonfish.base.model.menu.Menu;
import com.moonfish.base.repository.MenuRepository;
import com.moonfish.base.repository.RoleRepository;
import com.moonfish.base.model.security.Role;
import com.moonfish.base.security.JwtTokenUtil;
import com.moonfish.base.security.JwtUser;
import com.moonfish.base.utils.MapUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * Created by mayu on 2017/7/10.
 * email:showmara@qq.com
 */
@Api(value = "菜单管理", description = "菜单增删改查")
@RestController
@RequestMapping("/api/menus")
public class MenuRestController extends BaseController {
    @Autowired
    private MenuRepository menuRepository;
    @Autowired
    private RoleRepository roleRepository;

    public MenuRestController(JwtTokenUtil jwtTokenUtil, UserDetailsService userDetailsService) {
        super(jwtTokenUtil, userDetailsService);
    }

    @ApiOperation(value = "增加新菜单", notes = "添加新菜单", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParam(value = "令牌", name = "Authorization", required = true, paramType = "header", dataType = "String")
    @RequestMapping(method = RequestMethod.POST)
    @PreAuthorize("hasRole('ADMIN')")
    @Transactional
    public ResponseEntity<?> addMenu(@RequestBody MenuRequestBody menu) {
        List<Role> roles = new ArrayList<>();
        for (int i = 0; i < menu.getRoles().size(); i++) {
            roles.add(roleRepository.findById(menu.getRoles().get(i)));
        }

        Menu menu1 = new Menu();
        BeanUtils.copyProperties(menu,menu1);
        menu1.setAuthorities(roles);
        Menu temp = menuRepository.save(menu1);

        if (temp != null) {
            BaseResponseBody baseResponseBody = new BaseResponseBody(ErrCode.EXCEPTION, "ok", "", "");
            return ResponseEntity.ok(baseResponseBody);
        } else {
            BaseResponseBody baseResponseBody = new BaseResponseBody(ErrCode.OK, "ok", "", "");
            return ResponseEntity.ok(baseResponseBody);
        }
    }

    @ApiOperation(value = "删除菜单",notes = "删除菜单",produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParam(value = "令牌",name = "Authorization",required = true,paramType = "header",dataType = "String")
    @RequestMapping(method = RequestMethod.DELETE)
    @PreAuthorize("hasRole('ADMIN')")
    @Transactional
    public ResponseEntity<BaseResponseBody> deleteMenu(@RequestBody MenuRequestBody menuRequestBody) {
        if (menuRepository.findById(menuRequestBody.getId()) == null) {
            return ResponseEntity.ok(new BaseResponseBody(ErrCode.EXCEPTION, "无菜单ID", "", ""));
        } else {
            menuRepository.delete(menuRepository.findById(menuRequestBody.getId()));
            return ResponseEntity.ok(new BaseResponseBody(ErrCode.OK, "", "", ""));
        }
    }

    @ApiOperation(value = "修改菜单",notes = "修改菜单",produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParam(value = "令牌",name = "Authorization",required = true,paramType = "header",dataType = "String")
    @RequestMapping(method = RequestMethod.PUT)
    @PreAuthorize("hasRole('ADMIN')")
    @Transactional
    public ResponseEntity<BaseResponseBody<?>> updateMenu(@RequestBody MenuRequestBody menuRequestBody) {
        if (menuRepository.findById(menuRequestBody.getId()) == null) {
            return ResponseEntity.ok(new BaseResponseBody(ErrCode.EXCEPTION, "无菜单ID", "", ""));
        } else {
            Menu menu = menuRepository.findById(menuRequestBody.getId());
            ArrayList<Role> roles = new ArrayList<>();
            if(menuRequestBody.getRoles() != null && menuRequestBody.getRoles().size()>0) {
                for (int i = 0; i < menuRequestBody.getRoles().size(); i++) {
                    roles.add(roleRepository.findById(menuRequestBody.getRoles().get(i)));
                }
            }
            Map<String,Object> params = MapUtils.toMapTrimNull(menuRequestBody);

            MapUtils.apply(params,menu);

            menu.setAuthorities(roles);
            menuRepository.save(menu);
            return ResponseEntity.ok(new BaseResponseBody(ErrCode.OK, "", "", ""));
        }
    }


    @ApiOperation(value = "获取菜单",notes = "获取菜单",produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParam(value = "令牌",name = "Authorization",required = true,paramType = "header",dataType = "String")
    @RequestMapping(method = RequestMethod.GET)
    public ResponseEntity<MenuResponseBody> getMenu(HttpServletRequest request) {
        JwtUser jwtUser = getAuthenticatedUser(request);
        Collection<? extends GrantedAuthority> roles = jwtUser.getAuthorities();
        List<Menu> menus = new ArrayList<>();
        Iterator iterator = roles.iterator();
        while (iterator.hasNext()) {
            GrantedAuthority role = (GrantedAuthority) iterator.next();
            List<Menu> list = menuRepository.getMenuTree(role.getAuthority());
            menus.addAll(list);
        }

        List<MenuResponseBody.Router> routers = MenuResponseBody.makeRouter(menus);
//        List<Menu> m = buildTree(menus);
        List<MenuResponseBody.Router> routerList = buildRouters(routers);
        // 排序
        return ResponseEntity.ok(new MenuResponseBody(ErrCode.OK, "", "", routerList));
    }

    private List<Menu> buildTree(List<Menu> flat){
        Map<String, Menu> midStr = new HashMap<String, Menu>();

        /**把list中的数据 放到 map中，方便后续的查找*/
        for (int n = 0; n < flat.size(); n++) {
            midStr.put(flat.get(n).getId(), flat.get(n));
        }
        List<Menu> menuList = new ArrayList<Menu>();

        for (Map.Entry<String, Menu> entry : midStr.entrySet()) {
            Menu t = midStr.get(entry.getValue().getPid());
            if (t != null) {
                midStr.get(entry.getValue().getPid()).getChildren().add(entry.getValue());
            }else {
                menuList.add(entry.getValue());
            }
        }
        return menuList;
    }
    private List<MenuResponseBody.Router> buildRouters(List<MenuResponseBody.Router> flat){
        Map<String, MenuResponseBody.Router> midStr = new HashMap<String, MenuResponseBody.Router>();

        /**把list中的数据 放到 map中，方便后续的查找*/
        for (int n = 0; n < flat.size(); n++) {
            midStr.put(flat.get(n).getId(), flat.get(n));
        }
        List<MenuResponseBody.Router> menuList = new ArrayList<>();

        for (Map.Entry<String, MenuResponseBody.Router> entry : midStr.entrySet()) {
            MenuResponseBody.Router t = midStr.get(entry.getValue().getPid());
            if (t != null) {
                midStr.get(entry.getValue().getPid()).getChildren().add(entry.getValue());
            }else {
                menuList.add(entry.getValue());
            }
        }
        return menuList;
    }
}
